using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using viBook.Common;

namespace viBook.Models
{
    public class ChapterRepository : IChapterRepository
    {
        viBookContext _context = new viBookContext();
        readonly IPageRepository _pagerepository = new PageRepository();
        public IQueryable<Chapter> All
        {
            get { return _context.Chapters; }
        }

        public IQueryable<Chapter> AllIncluding(params Expression<Func<Chapter, object>>[] includeProperties)
        {
            IQueryable<Chapter> query = _context.Chapters;
            foreach (var includeProperty in includeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query;
        }

        public Chapter Find(int id)
        {
            Chapter chapter = _context.Chapters.Find(id);
            IQueryable<ChapterComment> totalComments = _context.Comments.Where(c => c.ChapterId == id);
            IQueryable<ChapterComment> comments = totalComments.OrderByDescending(c => c.CreatedDate).Take(Constant.MaximunCommentPerChapter);
            int noOfComments = totalComments.Count();
            if (chapter != null)
            {
                chapter.Comments = comments;
                chapter.NumberOfComments = noOfComments;
                chapter.NumberOfViews++;
                foreach (var page in chapter.Pages)
                {
                    page.Tags = new List<Tag>();
                }
                chapter.Book.ContentTags = new List<ContentTag>();
            }
           
           
            Save();
            return chapter;
        }

        public void InsertOrUpdate(Chapter chapter)
        {
            if (chapter.Id == default(int))
            {
                // New entity
                _context.Chapters.Add(chapter);
                Save();
                int numpage = 0;
                foreach (var page in chapter.Pages)
                {
                    numpage = numpage+1;
                    _pagerepository.InsertOrUpdate(new Page
                                                      {
                                                          Id = default(int),
                                                          ChapterId = chapter.Id,
                                                          ImageSource = page.ImageSource,
                                                          Number = numpage,
                                                      });
                }
            }
            else
            {
                // Existing entity
                _context.Entry(chapter).State = EntityState.Modified;
            }
        }

        public void Delete(int id)
        {
            Chapter chapter = _context.Chapters.Find(id);
            _context.Chapters.Remove(chapter);
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public void Like(int chapterId, int userId)
        {
            var chapterLike = new ChapterLike
                                  {
                                      ChapterId = chapterId,
                                      CreatedDate = DateTime.Now,
                                      UserId = userId
                                  };
            _context.ChapterLikes.Add(chapterLike);
            var chapter = Find(chapterId);
            chapter.NumberOfLikes++;
            InsertOrUpdate(chapter);
            Save();
        }

        public void DeleteChaptersInBook(int id)
        {
            foreach (var chapterid in _context.Chapters.Where(c =>c.BookId == id).Select(c =>c.Id))
            {
                  _pagerepository.DeletePagesInChapter(chapterid);  
                Delete(chapterid);
                Save();
            }
           
        }

        public List<ReportComment> GetAllChapterReport()
        {
            return _context.ReportComments.ToList();
        }

        public void Report(int chapterId, int userId)
        {
            var found = _context.ReportChapters.FirstOrDefault(r => r.ChapterId == chapterId && r.UserId == userId);
            if (found == null) return;
            var report = new ReportChapter
                             {
                                 ChapterId = chapterId,
                                 UserId = userId,
                                 ReportedDate = DateTime.Now
                             };
            _context.ReportChapters.Add(report);
            _context.SaveChanges();
        }

        public IQueryable<Chapter> GetAllChaptersByBookId(int bookId)
        {
            return _context.Chapters.
                Where(c => c.BookId == bookId);
        }
    }

    public interface IChapterRepository
    {
        IQueryable<Chapter> All { get; }
        IQueryable<Chapter> AllIncluding(params Expression<Func<Chapter, object>>[] includeProperties);
        Chapter Find(int id);
        void InsertOrUpdate(Chapter chapter);
        void Delete(int id);
        void Save();
        IQueryable<Chapter> GetAllChaptersByBookId(int bookId);

        void Like(int chapterId, int userId);
        void DeleteChaptersInBook(int id);
        List<ReportComment> GetAllChapterReport();
        void Report(int chapterId, int userId);
    }
}
